package cn.three.learn.server;

import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * @Description: 作用描述
 * @Author: hmm
 * @CreateDate: 2019/7/26$ 21:05$
 * @UpdateUser: hmm
 * @UpdateDate: 2019/7/26$ 21:05$
 * @UpdateRemark: 修改内容
 * @Version: 1.0
 */
@Component
@ChannelHandler.Sharable
@Slf4j
public class NettyServerHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
    /** 空闲次数 */
    private int idle_count = 1;
    /** 发送次数 */
    private int count = 1;

    /**
     * 建立连接时，发送一条消息
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.info("连接的客户端地址:" + ctx.channel().remoteAddress());
        ChannelSupervise.addChannel(ctx.channel());
        //super.channelActive(ctx);
        log.info("当前连接数：" + ChannelSupervise.count());
    }

    /**
     * 超时处理 如果5秒没有接受客户端的心跳，就触发; 如果超过两次，则直接关闭;
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object obj) throws Exception {
        if (obj instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) obj;
            // 如果读通道处于空闲状态，说明没有接收到心跳命令
            if (IdleState.READER_IDLE.equals(event.state())) {
                log.info("指定时间没有接收到客户端的信息了");
                if (idle_count > 1) {
                    log.info("关闭这个不活跃的channel");
                    ctx.channel().close();
                    ChannelSupervise.removeChannel(ctx.channel());
                }
                idle_count++;
            }
        } else {
            super.userEventTriggered(ctx, obj);
        }
    }

    /**
     * 业务逻辑处理
     */
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception {
        //这个方法：谁发的返回给谁
        //channelHandlerContext.writeAndFlush(new TextWebSocketFrame(textWebSocketFrame.text().toUpperCase()));
        /**
         * 这个方法：广播
         */
        ChannelSupervise.sendToAll(textWebSocketFrame);
    }

    /**
     * 异常处理
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        log.info("-------------------服务端关闭--------------");
        ctx.close();
    }
}
